package com.jse.server;

import com.jse.Fs;
import com.jse.Lang;
import com.jse.jakarta.View;
import com.jse.jakarta.Web;
import com.jse.json.JsonObject;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.KeyStore;
import java.time.Duration;
import java.util.concurrent.Executors;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

/**
 * Http server SUN using virtual threads to dispatch requests
 */
public class JdkHttpServer {

    HttpServer    httpServer;
    JsonObject configuration;


    private JdkHttpServer() {
        try {
            configuration = new JsonObject();
        } catch (Exception e) {
            throw new RuntimeException("读取配置失败");
        }
    }

    void init() {
        try {
            InetSocketAddress socketAddress = new InetSocketAddress(
            		InetAddress.getByName(configuration.getString("server.host","localhost")),
            		configuration.getInt("server.port",80));
            if (configuration.getBoolean("server.secure",false)) {
            	HttpsServer httpsServer = HttpsServer.create(socketAddress,
                		configuration.getInt("backlog",0));
//                configuration.get("Certificate")
//                        .init(httpsServer);
            	var keyStoreFile="";//证书文件地址
            	var storePassword="";//证书密码
            	var keyPassword="";//key密码
            	var alias="";//http.secure.alias
            	var protocol="HTTP/2.0";
            	FileInputStream fis      = new FileInputStream(keyStoreFile);
                KeyStore                 keySTore = KeyStore.getInstance("JSK");
                keySTore.load(fis, storePassword.toCharArray());
                var certificate = keySTore.getCertificate(alias);
                var keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
                var trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
                keyManagerFactory.init(keySTore, keyPassword.toCharArray());
                trustManagerFactory.init(keySTore);
                var sslContext = SSLContext.getInstance(protocol);
                sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
                
                httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
					@Override
                    public void configure(HttpsParameters params) {
                        try {
                            var context = SSLContext.getDefault();
                            var engine = context.createSSLEngine();
                            params.setNeedClientAuth(false);
                            params.setCipherSuites(engine.getEnabledCipherSuites());
                            params.setProtocols(engine.getEnabledProtocols());
                            var defaultSSslParameters = context.getDefaultSSLParameters();
                            params.setSSLParameters(defaultSSslParameters);
                        }
                        catch (Exception e) {
                            throw new IllegalStateException("Failed to setup server", e);
                        }
                    }
                });
                httpServer=httpsServer;
            } else {
                httpServer = HttpServer.create(socketAddress,configuration.getInt("backlog",0));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        httpServer.createContext("/",new HttpHandler() {
			
			@Override
			public void handle(HttpExchange ex) throws IOException {
				String url=ex.getRequestURI().getPath();
				String suffix=Fs.suffix(url);
				
				if(Lang.startsWith(url,Web.STATIC_PRIFIX)||Lang.endsWith(suffix.toLowerCase(),Web.STATIC_SUFFIX)) {
					View.staticforward.render(req,resp,null);;return;//静态文件转发
				}
			}
		});
        var executor = Executors.newVirtualThreadPerTaskExecutor();
        httpServer.setExecutor(executor);
    }

    public void start() {
        httpServer.start();
    }

    public void stop(Duration duration) {
        httpServer.stop(duration.toSecondsPart());
    }
    
    public static void main(String[] args) {
    	var server = new JdkHttpServer();
        server.init();
        server.start();
    }

}
